package dplr;

import bbcom.PropertiesType;
import bbcom.interfaces.IDeployer;
import bbcom.interfaces.IPropertiesParser;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.optional.ssh.SSHExec;
import org.apache.tools.ant.taskdefs.optional.ssh.Scp;
import org.apache.tools.ant.types.FileSet;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Thanh-Trung Pham.
 */
public class SSHDeployer implements IDeployer {

    private String m_strBaseFolderName;
    private IPropertiesParser m_oPropertiesParserPlugin;

    private Map<PropertiesType, List<String>> m_oDeployedElements = new HashMap<>();

    /**
     * The constructor.
     */
    public SSHDeployer() {
    }

    @Override
    public void setConfigurationSettings(String baseFolderName) {
        m_strBaseFolderName = baseFolderName;
    }

    @Override
    public void setPlugins(IPropertiesParser propertiesParserPlugin) {
        m_oPropertiesParserPlugin = propertiesParserPlugin;
    }

    @Override
    public void stopJava(PropertiesType properties, String commandArgs) {
        String strHost = m_oPropertiesParserPlugin.getHost(properties);
        int iHTTPPort = Integer.parseInt(m_oPropertiesParserPlugin.getProperty(properties, "httpPort"));

        StringBuilder oURI = new StringBuilder();
        oURI.append("http://");
        oURI.append(strHost);
        oURI.append(":");
        oURI.append(iHTTPPort);
        oURI.append("/jgbcontainer?stop");
        if(commandArgs != null){
            oURI.append(commandArgs);
        }

        HttpClient oHttpClient = new HttpClient();
        GetMethod oGetMethod = new GetMethod(oURI.toString());

        try {
            oHttpClient.executeMethod(oGetMethod);
        } catch (IOException oIgnoredIOException) {
            //TODO log into log files.
        }
    }


    @Override
    public void deployBBCoMInstanceFile(PropertiesType properties, String BBCoMInstanceFilename) {
        m_oDeployedElements.put(properties, new ArrayList<String>());

        Scp oScp = initializeScp(properties, "");

        FileSet oFileSet = new FileSet();
        oFileSet.setFile(new File(m_strBaseFolderName + File.separator + BBCoMInstanceFilename));
        oScp.addFileset(oFileSet);
        oScp.execute();
    }


    @Override
    public String getStartJava(final PropertiesType properties, final String commandArgs, final boolean isDebuggingEnable) {
        StringBuilder oCommands = new StringBuilder();

        oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "startJavaCommand")).append(" ");

        if (isDebuggingEnable) {
            oCommands.append("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=");
            oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "debuggingPort")).append(" ");
        }

        oCommands.append(commandArgs);
        return oCommands.toString();
    }

    /**
     * Initialize the SSHExe.
     *
     * @param properties the given properties.
     * @return the initialized SSHExec.
     */
    private SSHExec initializeSSHExec(PropertiesType properties) {
        String strHost = m_oPropertiesParserPlugin.getHost(properties);
        String strPassword = m_oPropertiesParserPlugin.getProperty(properties, "password");
        String strUsername = m_oPropertiesParserPlugin.getProperty(properties, "username");
        int iSSHPort = Integer.parseInt(m_oPropertiesParserPlugin.getProperty(properties, "sshPort"));

        SSHExec oReturnSSHExec = new SSHExec();
        oReturnSSHExec.setTrust(true);
        oReturnSSHExec.setHost(strHost);
        oReturnSSHExec.setPort(iSSHPort);
        oReturnSSHExec.setUsername(strUsername);
        oReturnSSHExec.setPassword(strPassword);

        return oReturnSSHExec;
    }


    /**
     * Initialize the Scp.
     *
     * @param properties the given properties.
     * @param toDir      the target directory.
     */
    private Scp initializeScp(PropertiesType properties, String toDir) {
        String strHost = m_oPropertiesParserPlugin.getHost(properties);
        String strPassword = m_oPropertiesParserPlugin.getProperty(properties, "password");
        String strUsername = m_oPropertiesParserPlugin.getProperty(properties, "username");
        int iSSHPort = Integer.parseInt(m_oPropertiesParserPlugin.getProperty(properties, "sshPort"));

        String strDeploymentDir = m_oPropertiesParserPlugin.getProperty(properties, "deploymentDir");

        Scp oReturnScp = new Scp();

        oReturnScp.setTrust(true);
        oReturnScp.setProject(new Project());
        oReturnScp.setPort(iSSHPort);

        oReturnScp.setTodir(strUsername + ":" + strPassword + "@" + strHost + ":" + strDeploymentDir + "/" + toDir);

        return oReturnScp;

    }

    @Override
    public void deployDependencyFiles(PropertiesType properties, List<String> dependencyFilenames) {
        List<String> oDeployedDependencies = m_oDeployedElements.get(properties);

        for (String strFilename : dependencyFilenames) {
            if (strFilename.endsWith(".class") || strFilename.endsWith(".jar")) {
                //don't support deploy *.jar or *.class, these files should be included in a folder to deploy.
                continue;
            }


            if (oDeployedDependencies.contains(strFilename)) {
                continue;
            }

            oDeployedDependencies.add(strFilename);

            SSHExec oSSHExec = initializeSSHExec(properties);
            StringBuilder oCommands = new StringBuilder();
            oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "changeDirCommand")).append(" ");
            oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "deploymentDir"));
            oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "commandSeparator"));
            oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "makeDirCommand")).append(" ");
            oCommands.append(strFilename);
            oCommands.append(m_oPropertiesParserPlugin.getProperty(properties, "commandSeparator"));
            oSSHExec.setCommand(oCommands.toString());
            oSSHExec.execute();

            Scp oScp = initializeScp(properties, strFilename);
            FileSet oFileSet = new FileSet();
            oFileSet.setDir(new File(m_strBaseFolderName + File.separator + strFilename));
            oScp.addFileset(oFileSet);
            oScp.execute();
        }
    }


}
